<template>
  <div class="ofd_view">
    <el-header>
      <div style="display: flex;">
        <div class="upload" @click="uploadFile">
          <div class="upload_title">打开OFD</div>
          <input type="file" ref="file" class="hidden" accept=".ofd"
                 @change="fileChanged">
        </div>
        <div class="scale-icon" @click="firstPage">
          <i class="el-icon-d-arrow-left"/>
        </div>
        <div class="scale-icon" style="font-size: 18px;" @click="prePage">
          <i class="el-icon-arrow-left"/>
        </div>
        <div class="page-input" style="width: 80px;">
          <el-input v-model="pageIndex" @input="changePage"></el-input>
          /{{ pageCount }}
        </div>
        <div class="scale-icon" style="font-size: 18px" @click="nextPage">
          <i class="el-icon-arrow-right"/>
        </div>
        <div class="scale-icon" @click="lastPage">
          <i class="el-icon-d-arrow-right"/>
        </div>
      </div>
      <div style="display: flex;">
        <div class="scale-icon" title="缩小" @click="minus">
          <i class="el-icon-minus"/>
        </div>
        |
        <div class="scale-icon" title="放大" @click="plus">
          <i class="el-icon-plus"/>
        </div>
        <el-select v-model="showScale" placeholder="缩放" @change="changeScale" style="margin-left: 10px">
          <el-option
              v-for="(item,index) in scaleList"
              :key="index"
              :label="item.label"
              :value="item.value">
          </el-option>
        </el-select>
      </div>
      <div class="scale-icon" id="printOfd" title="打印" @click="printOfd">
        <i class="el-icon-printer"/>
      </div>
    </el-header>
    <div class="ofd_main" id="ofd_main">
      <div v-loading="loading" class="ofdContainer" id="ofdContainer" ref="contentDiv" @mousewheel="scrool"></div>
    </div>

    <el-dialog
        title="验签结果"
        :visible.sync="dialogVisible"
    >
      <el-form label-width="100px" :model="signatureInfo">
        <el-form-item label="签章人：">
          <el-input v-model="signatureInfo.signer"></el-input>
        </el-form-item>
        <el-form-item label="签章提供者：">
          <el-input v-model="signatureInfo.provider"></el-input>
        </el-form-item>
        <el-form-item label="原文摘要值：">
          <el-input v-model="signatureInfo.hashedValue"></el-input>
        </el-form-item>
        <el-form-item label="签名值：">
          <el-input v-model="signatureInfo.signedValue"></el-input>
        </el-form-item>
        <el-form-item label="签名算法：">
          <el-input v-model="signatureInfo.signMethod"></el-input>
        </el-form-item>
        <el-form-item label="版本号：">
          <el-input v-model="signatureInfo.version"></el-input>
        </el-form-item>
        <el-form-item label="验签结果：">
          <el-input ref="VerifyRet" v-model="signatureInfo.VerifyRet"></el-input>
        </el-form-item>
        <el-form-item label="印章标识：">
          <el-input v-model="signatureInfo.sealID"></el-input>
        </el-form-item>
        <el-form-item label="印章名称：">
          <el-input v-model="signatureInfo.sealName"></el-input>
        </el-form-item>
        <el-form-item label="印章类型：">
          <el-input v-model="signatureInfo.sealType"></el-input>
        </el-form-item>
        <el-form-item label="有效时间：">
          <el-input v-model="signatureInfo.sealAuthTime"></el-input>
        </el-form-item>
        <el-form-item label="制章日期：">
          <el-input v-model="signatureInfo.sealMakeTime"></el-input>
        </el-form-item>
        <el-form-item label="印章版本：">
          <el-input v-model="signatureInfo.sealVersion"></el-input>
        </el-form-item>
      </el-form>
    </el-dialog>
  </div>
</template>

<script>
import {digestCheck, getPageScale, parseOfdDocument, renderOfd, renderOfdByScale, setPageScale} from "./ofd/index.js";
import {base64ToFile} from "@/utils";

export default {
  props: ['activeOfdId'],
  data() {
    return {
      dialogVisible: false,// 弹窗
      signatureInfo: {},// 签章信息
      loading: false,//加载中
      pageIndex: 1, // 当前页码
      pageCount: 0, // 总页数
      ofdBase64: '', // ofd文件base64
      scale: 0, // 缩放比例
      showScale: 0, // 展示缩放比例
      originalScale: 0, // 原始比例
      scaleList: [
        {value: 0, label: '自适应'},
        {value: 0.5, label: '实际大小'},
        {value: 2.5, label: '50%'},
        {value: 3.75, label: '75%'},
        {value: 5, label: '100%'},
        {value: 6.25, label: '125%'},
        {value: 7.5, label: '150%'},
        {value: 10, label: '200%'},
      ],
      screenWidth: document.body.clientWidth,
      domWidth: 0,
      // screenWidth: 1000,
      ofdObj: null, // ofd文件对象
      file: null, // 上传的文件
    }
  },
  watch: {
    // 页面大小变化时，重新渲染ofd
    domWidth() {
      if (this.showScale === 0) {
        const divs = renderOfd(this.domWidth, this.ofdObj);
        this.displayOfdDiv(divs);
      }
    },
    // 监控activeOfdId变化，重新渲染ofd
    activeOfdId(val) {
      if (val) {
        this.loading = true;
        this.showScale = 0;
        this.getOfdFile();
      }
    }
  },
  mounted() {
    let that = this;
    this.$refs.contentDiv.addEventListener('scroll', this.scrool);
    // 监控ofd_main的宽度变化(自适应大小)
    let elementResizeDetectorMaker = require("element-resize-detector")
    let erd = elementResizeDetectorMaker();
    erd.listenTo(document.getElementsByClassName("ofd_main"), function (element) {
      let width = element.offsetWidth;
      let height = element.offsetHeight;
      // console.log("width: " + width + "height：" + height);
      that.domWidth = width - 500;
    });
  },
  methods: {
    // 鼠标滚动
    scrool() {
      let scrolled = this.$refs.contentDiv.firstElementChild?.getBoundingClientRect()?.top - 60;
      let top = 0
      let index = 0;
      for (let i = 0; i < this.$refs.contentDiv.childElementCount; i++) {
        top += (Math.abs(this.$refs.contentDiv.children.item(i)?.style.height.replace('px', '')) + Math.abs(this.$refs.contentDiv.children.item(i)?.style.marginBottom.replace('px', '')));
        if (Math.abs(scrolled) < top) {
          index = i;
          break;
        }
      }
      this.pageIndex = index + 1;
    },

    // 显示ofd
    displayOfdDiv(divs) {
      this.scale = getPageScale();
      let contentDiv = document.getElementById('ofdContainer');
      contentDiv.innerHTML = '';
      for (const div of divs) {
        contentDiv.appendChild(div)
      }
      for (let ele of document.getElementsByName('seal_img_div')) {
        this.addEventOnSealDiv(ele, JSON.parse(ele.dataset.sesSignature), JSON.parse(ele.dataset.signedInfo));
      }
      this.loading = false;
    },

    // 放大
    plus() {
      this.scale = Number(this.scale + '');
      let value = Math.round(this.scale)
      if (value <= this.scale) {
        this.scale = value + 0.5;
      } else {
        this.scale = value
      }
      setPageScale(this.scale);
      const divs = renderOfdByScale(this.ofdObj);
      this.displayOfdDiv(divs);
      this.showScale = ((this.scale * 100) / 5) + '%';
    },

    // 缩小
    minus() {
      this.scale = Number(this.scale + '');
      let value = Math.floor(this.scale)
      if (value >= this.scale) {
        this.scale = value - 0.5;
      } else {
        this.scale = value
      }
      setPageScale(this.scale);
      const divs = renderOfdByScale(this.ofdObj);
      this.displayOfdDiv(divs);
      this.showScale = ((this.scale * 100) / 5) + '%';
    },

    // 选择比例
    changeScale() {
      if (this.showScale === 0) {
        const divs = renderOfd(this.domWidth, this.ofdObj);
        this.displayOfdDiv(divs);
      } else if (this.showScale === 0.5) {
        const divs = renderOfd(this.screenWidth, this.ofdObj);
        this.displayOfdDiv(divs);
      } else {
        this.scale = this.showScale;
        setPageScale(this.scale);
        const divs = renderOfdByScale(this.ofdObj);
        this.displayOfdDiv(divs);
      }
    },

    // 修改页码
    changePage() {
      if (this.pageIndex > this.pageCount) {
        this.pageIndex = this.pageCount;
      } else if (this.pageIndex < 1) {
        this.pageIndex = 1;
      }
      let contentDiv = document.getElementById('ofdContainer');
      let ele = contentDiv.children.item(this.pageIndex - 1);
      ele?.scrollIntoView(true);
    },

    // 上一页
    prePage() {
      let contentDiv = document.getElementById('ofdContainer');
      let ele = contentDiv.children.item(this.pageIndex - 2);
      ele?.scrollIntoView(true);
      ele ? this.pageIndex = this.pageIndex - 1 : '';
    },

    // 第一页
    firstPage() {
      let contentDiv = document.getElementById('ofdContainer');
      let ele = contentDiv.firstElementChild;
      ele?.scrollIntoView(true);
      ele ? this.pageIndex = 1 : '';
    },

    // 下一页
    nextPage() {
      let contentDiv = document.getElementById('ofdContainer');
      let ele = contentDiv.children.item(this.pageIndex);
      ele?.scrollIntoView(true);
      ele ? ++this.pageIndex : '';
    },

    // 最后一页
    lastPage() {
      let contentDiv = document.getElementById('ofdContainer');
      let ele = contentDiv.lastElementChild;
      ele?.scrollIntoView(true);
      ele ? this.pageIndex = contentDiv.childElementCount : '';
    },

    // 打印ofd文件
    async printOfd() {
      /*if (this.showScale !== 0) {
        this.showScale = 0;
        const divs = renderOfd(this.domWidth, this.ofdObj);
        await this.displayOfdDiv(divs);
      }*/
      let childs = this.$refs.contentDiv.children;
      let list = [];
      for (let page of childs) {
        list.push(page.cloneNode(true));
      }
      if (list.length > 0) {
        let printWindow = window.open("打印窗口", "_blank");
        //给新打开的标签页添加画布内容
        let documentBody = printWindow.document.body;
        // 需要给新打开的标签页添加样式，否则打印出来的内容会很错位
        documentBody.style.marginTop = '20px';
        for (let page of list) {
          // 为了让打印的内容不会太靠上，所以给每一页都添加一个marginBottom
          page.style.marginBottom = '20px';
          documentBody.appendChild(page);
        }
        //焦点移到新打开的标签页
        printWindow.focus();
        //执行打印的方法（注意打印方法是打印的当前窗口内的元素，所以前面才新建一个窗口：print()--打印当前窗口的内容。）
        printWindow.print();
        //操作完成之后关闭当前标签页（点击确定或者取消都会关闭）
        printWindow.close();
      }
    },

    // 上传文件点击
    uploadFile() {
      this.file = null;
      this.$refs.file.click();
    },

    // 上传文件
    fileChanged() {
      this.file = this.$refs.file.files[0];
      let ext = this.file.name.replace(/.+\./, "");
      if (["ofd"].indexOf(ext) === -1) {
        this.$alert('error', '仅支持ofd类型', {
          confirmButtonText: '确定',
          callback: action => {
            this.$message({
              type: 'info',
              message: `action: ${action}`
            });
          }
        });
        return;
      }
      if (this.file.size > 100 * 1024 * 1024) {
        this.$alert('error', '文件大小需 < 100M', {
          confirmButtonText: '确定',
          callback: action => {
            this.$message({
              type: 'info',
              message: `action: ${action}`
            });
          }
        });
        return;
      }
      let that = this;
      let reader = new FileReader();
      reader.readAsDataURL(this.file);
      reader.onload = function (e) {
        that.ofdBase64 = e.currentTarget.result.split(',')[1];
      }
      this.viewOfd(this.file, this.domWidth);
      this.$refs.file.value = null;
    },

    // 渲染ofd
    viewOfd(file, screenWidth) {
      let that = this;
      // 其中ofd传入的file支持本地文件、二进制或者url、screenWidth为屏幕宽度
      parseOfdDocument({
        ofd: file,
        success(res) {
          that.ofdObj = res[0]
          that.pageCount = res[0].pages.length;
          // 输出ofd每页的div
          const contentDiv = document.getElementById('ofdContainer');
          contentDiv.innerHTML = '';
          const divs = renderOfd(screenWidth, res[0])
          that.originalScale = getPageScale();
          that.displayOfdDiv(divs);
        },
        fail(error) {
          console.log(error)
        }
      })
    },

    // 签章添加点击事件
    addEventOnSealDiv(div, SES_Signature, signedInfo) {
      global.HashRet = null;
      global.VerifyRet = signedInfo.VerifyRet;
      const that = this
      div.addEventListener("click", () => {
        console.log("点击了签章");
        if (SES_Signature.realVersion < 4) {
          this.signatureInfo.signer = SES_Signature.toSign.cert['commonName'].str;
          this.signatureInfo.provider = signedInfo.Provider['@_ProviderName'];
          this.signatureInfo.hashedValue = SES_Signature.toSign.dataHash.replace(/\n/g, '');
          this.signatureInfo.signedValue = SES_Signature.signature.replace(/\n/g, '');
          this.signatureInfo.signMethod = SES_Signature.toSign.signatureAlgorithm.replace(/\n/g, '');
          this.signatureInfo.sealID = SES_Signature.toSign.eseal.esealInfo.esID.str;
          this.signatureInfo.sealName = SES_Signature.toSign.eseal.esealInfo.property.name.str;
          this.signatureInfo.sealType = SES_Signature.toSign.eseal.esealInfo.property.type;
          this.signatureInfo.sealAuthTime = "从 " + SES_Signature.toSign.eseal.esealInfo.property.validStart + " 到 " + SES_Signature.toSign.eseal.esealInfo.property.validEnd;
          this.signatureInfo.sealMakeTime = SES_Signature.toSign.eseal.esealInfo.property.createDate;
          this.signatureInfo.sealVersion = SES_Signature.toSign.eseal.esealInfo.header.version;
        } else {
          this.signatureInfo.signer = SES_Signature.cert['commonName'].str;
          this.signatureInfo.provider = signedInfo.Provider['@_ProviderName'];
          this.signatureInfo.hashedValue = SES_Signature.toSign.dataHash.replace(/\n/g, '');
          this.signatureInfo.signedValue = SES_Signature.signature.replace(/\n/g, '');
          this.signatureInfo.signMethod = SES_Signature.signatureAlgID.replace(/\n/g, '');
          this.signatureInfo.sealID = SES_Signature.toSign.eseal.esealInfo.esID.str;
          this.signatureInfo.sealName = SES_Signature.toSign.eseal.esealInfo.property.name.str;
          this.signatureInfo.sealType = SES_Signature.toSign.eseal.esealInfo.property.type;
          this.signatureInfo.sealAuthTime = "从 " + SES_Signature.toSign.eseal.esealInfo.property.validStart + " 到 " + SES_Signature.toSign.eseal.esealInfo.property.validEnd;
          this.signatureInfo.sealMakeTime = SES_Signature.toSign.eseal.esealInfo.property.createDate;
          this.signatureInfo.sealVersion = SES_Signature.toSign.eseal.esealInfo.header.version;
        }
        this.signatureInfo.version = SES_Signature.toSign.version;
        this.signatureInfo.VerifyRet = "文件摘要值后台验证中，请稍等... " + (global.VerifyRet ? "签名值验证成功" : "签名值验证失败");
        if (global.HashRet == null || global.HashRet == undefined || Object.keys(global.HashRet).length <= 0) {
          // debugger
          setTimeout(() => {
            const signRetStr = global.VerifyRet ? "签名值验证成功" : "签名值验证失败";
            global.HashRet = digestCheck(global.toBeChecked.get(signedInfo.signatureID));
            const hashRetStr = global.HashRet ? "文件摘要值验证成功" : "文件摘要值验证失败";
            that.$refs.VerifyRet.value = hashRetStr + " " + signRetStr;
            that.signatureInfo.VerifyRet = hashRetStr + " " + signRetStr;
          }, 1000);
        }
        this.dialogVisible = true;
      })
    },

    // 获取ofd文件
    getOfdFile() {
      const ofdDoc = sessionStorage.getItem('ofdDoc') ? JSON.parse(sessionStorage.getItem('ofdDoc')) : {}
      const ofdFile = base64ToFile(ofdDoc)
      this.viewOfd(ofdFile, this.domWidth);
    }
  }
}
</script>
<style lang="scss" scoped>
.ofd_view {
  width: 100%;
  height: 100%;
  overflow: auto;

  .el-header {
    height: 40px !important;
    line-height: 40px;
    background-color: #f7f7f7;
    //border-bottom: 1px solid #bebebe;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: space-between;

    .upload {
      align-self: center;
      height: 32px;
      line-height: 32px;
      width: 80px;
      border-radius: 3px;
      float: left;
      margin-left: 20px;

      .upload_title {

      }
    }

    .upload:hover {
      cursor: pointer;
      background-color: #e6e6e6;
    }

    .scale-icon {
      align-self: center;
      height: 32px;
      line-height: 32px;
      width: 36px;
      border-radius: 3px;

      .el-icon-minus {
        color: #909399;
        font-weight: bold;
      }

      .el-icon-plus {
        color: #909399;
        font-weight: bold;
      }
    }

    .scale-icon:hover {
      cursor: pointer;
      background-color: #e6e6e6;
    }

    .page-input {
      align-self: center;
      height: 32px;
      line-height: 32px;
      width: 40px;
      border-radius: 3px;

      .el-input {
        width: 40px;

        .el-input__inner {
          height: 32px;
        }
      }
    }
  }

  .ofd_main {
    width: 100%;
    height: calc(100% - 40px);
    overflow: auto;
    background: #ededf0;

    .ofdContainer {
      padding-top: 20px;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      background: #ededf0;
      overflow: hidden;
    }
  }
}
</style>
<style>
.hidden {
  display: none !important;
}

.ofd-page {
  box-shadow: 0 0 10px #ccc;
}

.el-input__inner {
  height: 32px;
}
</style>
